/*
 * Title:        CloudSim Toolkit
 * Description:  CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 *
 * Copyright (c) 2009-2012, The University of Melbourne, Australia
 */

package org.cloudbus.cloudsim.provisioners;

import org.cloudbus.cloudsim.Vm;

import java.util.HashMap;
import java.util.Map;

/**
 * BwProvisionerSimple is an extension of {@link BwProvisioner} which uses a best-effort policy to
 * allocate bandwidth (bw) to VMs: 
 * if there is available bw on the host, it allocates; otherwise, it fails. 
 * Each host has to have its own instance of a RamProvisioner.
 * 
 * @author Rodrigo N. Calheiros
 * @author Anton Beloglazov
 * @since CloudSim Toolkit 1.0
 */
public class DiskProvisionerSimple extends DiskProvisioner {

	/** The BW map, where each key is a VM id and each value
         * is the amount of BW allocated to that VM. */
	private Map<String, Long> DiskTable;

	/**
	 * Instantiates a new disk provisioner simple.
	 *
	 * @param disk The total disk capacity from the host that the provisioner can allocate to VMs.
	 */
	public DiskProvisionerSimple(long disk) {
		super(disk);
		setDiskTable(new HashMap<String, Long>());
	}

	@Override
	public boolean allocateDiskForVm(Vm vm, long disk) {
		deallocateDiskForVm(vm);

		if (getAvailableDisk() >= disk) {
			setAvailableDisk(getAvailableDisk() - disk);
			getDiskTable().put(vm.getUid(), disk);
			vm.setCurrentAllocatedDisk(getAllocatedDiskForVm(vm));
			return true;
		}

		vm.setCurrentAllocatedDisk(getAllocatedDiskForVm(vm));
		return false;
	}

	@Override
	public long getAllocatedDiskForVm(Vm vm) {
		if (getDiskTable().containsKey(vm.getUid())) {
			return getDiskTable().get(vm.getUid());
		}
		return 0;
	}

	@Override
	public void deallocateDiskForVm(Vm vm) {
		if (getDiskTable().containsKey(vm.getUid())) {
			long amountFreed = getDiskTable().remove(vm.getUid());
			setAvailableDisk(getAvailableDisk() + amountFreed);
			vm.setCurrentAllocatedDisk(0);
		}
	}

	@Override
	public void deallocateDiskForAllVms() {
		super.deallocateDiskForAllVms();
		getDiskTable().clear();
	}

	@Override
	public boolean isSuitableForVm(Vm vm, long disk) {
		long allocatedDisk = getAllocatedDiskForVm(vm);
		boolean result = allocateDiskForVm(vm, disk);
		deallocateDiskForVm(vm);
		if (allocatedDisk > 0) {
			allocateDiskForVm(vm, allocatedDisk);
		}
		return result;
	}

	/**
	 * Gets the map between VMs and allocated bw.
	 * 
	 * @return the bw map
	 */
	protected Map<String, Long> getDiskTable() {
		return DiskTable;
	}

	/**
	 * Sets the map between VMs and allocated bw.
	 * 
	 * @param bwTable the bw map
	 */
	protected void setDiskTable(Map<String, Long> bwTable) {
		this.DiskTable = bwTable;
	}

}
